package se.webbzon.boltzmann.game.sequence;

import java.awt.Point;
import java.util.Stack;

import se.webbzon.boltzmann.game.object.dialogue.ChoiceDialogue;
import se.webbzon.boltzmann.game.object.dialogue.IntegerDialogue;
import se.webbzon.boltzmann.game.object.dialogue.ItemDialogue;
import se.webbzon.boltzmann.game.object.player.AbstractPlayerCharacter;
import se.webbzon.boltzmann.game.sequence.builder.AbstractSequenceBinding;
import se.webbzon.boltzmann.inventory.Inventory;
import se.webbzon.boltzmann.item.AbstractItem;
import se.webbzon.boltzmann.player.Player;
import se.webbzon.oschi01.worldobject.WorldObject;

public enum SequenceKey {

	CHARACTER {
		@Override public Object get(Sequence seq) {
			return getPlayer(seq).getCharacter().getName();
		}
	}, 
	COINS {
		@Override public Object get(Sequence seq) {
			return (double) getPlayer(seq).getCoins().getCoins();
		}
		@Override public void set(Sequence seq, double value) {
			getPlayer(seq).getCoins().setCoins((int) value); 
		}
	}, 
	HEALTH { 
		@Override public Object get(Sequence seq) {
			return (double) getPlayer(seq).getHealth().getHealth();
		}
		@Override public void set(Sequence seq, double value) {
			getPlayer(seq).getHealth().setHealth((int) value); 
		}
	}, 
	LAST_SELECTION {
		@Override public Object get(Sequence seq) {
			return (double) lastChoiceDialogue(seq).getSelection();
		}
	}, 
	LAST_CHOICE {
		@Override public Object get(Sequence seq) {
			return lastChoiceDialogue(seq).getChoice();
		}
	}, 
	LAST_INTEGER {
		@Override public Object get(Sequence seq) {
			return (double) lastIntegerDialogue(seq).getValue();
		}
	}, 
	LAST_ITEM_INDEX {
		@Override public Object get(Sequence seq) {
			Point p = new Point();
			lastItemDialogue(seq).getItemPosition(p);
			Inventory inv = getPlayer(seq).getInventory();
			return p.getY() + inv.getColumns() * p.getX();
		}
	},
	LAST_ITEM_NAME {
		@Override public Object get(Sequence seq) {
			AbstractItem item = lastItemDialogue(seq).getItem();
			return item == null ? "" : item.getName();
		}
	};
	
	/*============================================================
	Public Methods
	============================================================*/

	/** Returns the value of this special variable. **/
	public Object get(Sequence seq) {return 0;};

	/** Sets the value of this special variable. **/
	public void set(Sequence seq, double value) {};

	/** Sets the value of this special variable. **/
	public void set(Sequence seq, String str) {};
	
	/*============================================================
	Private Methods
	============================================================*/
	
	/** Returns the player associated with the given sequence. **/
	private static final Player getPlayer(Sequence sequence) {
		WorldObject wso = 
				sequence.getBinding(AbstractSequenceBinding.PLAYER);
		if (wso == null)
			return null;
		else
			return ((AbstractPlayerCharacter) wso).getPlayer();
	}
	
	/** Returns the last choice dialogue in the sequence. **/
	private static final ChoiceDialogue lastChoiceDialogue(Sequence sequence) {
		Stack<SequenceNode> stack = sequence.getStack();
		for (int i = stack.size()-1; i >= 0; i--) {
			SequenceNode node = stack.get(i);
			if (node instanceof ChoiceDialogueSequenceNode) {
				ChoiceDialogueSequenceNode dialogueNode = 
						(ChoiceDialogueSequenceNode) node;
				return (ChoiceDialogue) dialogueNode.getDialogue();
			}
		}
		return null;
	}
	
	/** Returns the last integer dialogue in the sequence. **/
	private static final IntegerDialogue lastIntegerDialogue(Sequence sequence) {
		Stack<SequenceNode> stack = sequence.getStack();
		for (int i = stack.size()-1; i >= 0; i--) {
			SequenceNode node = stack.get(i);
			if (node instanceof IntegerDialogueSequenceNode) {
				IntegerDialogueSequenceNode dialogueNode = 
						(IntegerDialogueSequenceNode) node;
				return (IntegerDialogue) dialogueNode.getDialogue();
			}
		}
		return null;
	}
	
	/** Returns the last item dialogue in the sequence. **/
	private static final ItemDialogue lastItemDialogue(Sequence sequence) {
		Stack<SequenceNode> stack = sequence.getStack();
		for (int i = stack.size()-1; i >= 0; i--) {
			SequenceNode node = stack.get(i);
			if (node instanceof ItemDialogueSequenceNode) {
				ItemDialogueSequenceNode dialogueNode = 
						(ItemDialogueSequenceNode) node;
				return (ItemDialogue) dialogueNode.getDialogue();
			}
		}
		return null;
	}

}
